﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace theRift
{
    public class WorldScene : GameScene
    {
        // For debugging purposes mainly add an FPS counter, gives a
        // general impression of performance
        private FPS fps;
        
        // Player and camera
        protected Player player;
        protected ThirdPersonCamera camera;
        protected bool cameraSpringEnabled = false;

        // Terrain and terrain intersection
        protected Terrain terrain;
        protected Vector3 pointerPos;
        protected Vector2 pointerScreenPos;

        #region Properties

        public Player Player
        {
            get { return player; }
            set { player = value; }
        }

        #endregion

        public WorldScene(Game game)
            : base(game)
        {
            Initialize(game);
        }

        public void Initialize(Game game)
        {
            modelManager = new ModelManager(game);
            
            terrain = new Terrain(game, new Vector2(1.0f, 1.0f));
            terrain.LoadHeightData("heightmap");
            Components.Add(terrain);

#if DEBUG
            fps = new FPS(game);
#else
            fps = new FPS(game, true, false);
#endif
            
            // Player generated here, for now default positions are used.
            // Should of course at some point be read out from some form of
            // a save file.
            player = new Player(game);
            player.Model = new AnimatedModel(game);
            player.Model.Load("character");
            player.EntityType = EntityType.Player;
            player.PhysicalState.Position = new Vector3(0, 100.0f, 0);
            player.PhysicalState.Velocity = Vector3.Zero;
            player.PhysicalState.Scale = new Vector3(1.0f, 1.0f, 1.0f);
            player.CurHealth = 5;
            player.MaxHealth = 7;
            gui.Player = player; // Inform the GUI of which entity to display data from

            // Third person camera with several of the parameters defined.
            // Aspectratio is defined below the base.Initialize(); call.
            camera = new ThirdPersonCamera();        
            //camera.DesiredPositionOffset = new Vector3(0.0f, 10.0f, 3.0f);
            //camera.LookAtOffset = new Vector3(0.0f, 1.0f, 0.0f);
            camera.DesiredPositionOffset = new Vector3(0.0f, 1.0f, 1.0f);
            camera.LookAtOffset = new Vector3(0.0f, 1.0f, 0.0f);
            camera.FOV = MathHelper.PiOver4;
            camera.NearPlane = 1.0f;
            camera.FarPlane = 10000.0f;
            camera.AspectRatio = (float)game.GraphicsDevice.Viewport.Width /
                game.GraphicsDevice.Viewport.Height;

            // Game components, update and draw happens in the order they are
            // defined!!
            Components.Add(modelManager);
            Components.Add(gui);
            Components.Add(fps);

            // Lights added to lightmanager
            lightManager.Add("Light1", new PointLight(Vector3.One, new Vector3(0, 500.0f, 1000.0f)));

            // Camera additions to the cameramanager, if more than one
            // is to be added be sure to use cameraManager.SetActiveCamera
            // or cameraManager.SetActiveCameraIndex to select the desired
            // starter cam.
            cameraManager.Add("Third Person Camera", camera);

            // Make sure our camera starts out in the correct position rather
            // than racing through the world trying to trace the character.
            UpdateCamera();
            camera.Reset();

            // Modelmanager, draws and updates model in order of addition.
            // Be sure to add the models to the model manager (preferably here)
            // if desired for the draw and update to be handled by it. Otherwise
            // don't forget to manually draw and update it!! [not recommended]
            modelManager.AddModel(player.Model);

            pointerScreenPos = new Vector2(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
        }

        private TextureMaterial LoadTextureMaterial(Game game, string textureFilename, Vector2 tile)
        {
            Texture2D texture = game.Content.Load<Texture2D>(Directories.TEXTURES_PATH + textureFilename);
            return new TextureMaterial(texture, tile);
        }

        public override void Update(GameTime gameTime)
        {
            player.Update(gameTime);

            // Update the camera position based on direct input and
            // player input.
            UpdateCamera();

            // The chase camera's update behavior is the springs, but we can
            // use the Reset method to have a locked, spring-less camera
            if (cameraSpringEnabled)
            {
                camera.Update(gameTime);
            }
            else
                camera.Reset();

            MouseState mouseState = Mouse.GetState();
            pointerScreenPos = new Vector2(mouseState.X, mouseState.Y);

            if (inputState.IsMouseButtonDown(MouseButtons.MiddleButton))
            {
                terrain.GetPosition(pointerScreenPos, out pointerPos);
            }

            Game.Window.Title = "Eureka! {" + pointerPos.X + "} {" + pointerPos.Y + "} {" + pointerPos.Z + "}";

            base.Update(gameTime);
        }

        private void UpdateCamera()
        {
            camera.ChasePosition = player.PhysicalState.Position;
            camera.Direction = player.PhysicalState.Direction;
            camera.Up = player.PhysicalState.Up;

            camera.DesiredPositionOffsetY += inputState.ScrollWheelDelta;
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
        }
    }
}
